% -----------
% Copyright 2013-2014, Andrew Lindesay
% Distributed under the terms of the MIT License.
% -----------

\section{API}
\label{api}

\subsection{General}

This information applies to all areas of the API for the system; both JSON-RPC and REST packaged.

\subsubsection{Clients}

A client of this system's API may be a desktop application (eg; Haiku Depot) or may be logic in a web page where the web page is using some java-script to call back to the server.

\subsubsection{API Version}

The application generally refers to ``api 1'' in anticipation that at some point there is the {\it possibility} that a second, incompatible API may be required.

\subsubsection{Object References}

When objects such as packages or users are referred to in the API, the database primary key is {\bf not} used.  Instead either a natural or artifical identifier is employed.  For example, in the case of a package, the package's name may be used.  In the case of a screen-shot, a GUID (unique identifier) will be used to identify a particular screenshot.

\subsubsection{Reference Data}

Reference data means data in the application that is generally invariant.  Examples include the mime types, natural language, url types and so on.  In these cases, an API will generally provide for access to the list of reference data.  The client is expected to obtain such reference data as necessary and cache reference data locally.

\subsubsection{Date and Time Data}

The system has only a concept of a {\it moment in time} which is called a timestamp.  The timestamp is typically communicated as the number of milliseconds elapsed since the epoc represented as a 64bit integer.  The timestamp communicated via the API is always relative to UTC.

\subsubsection{Invocations and Transport}

The term ``invocation'' refers to a request-response cycle from the client software into the application server over the HTTP protocol.  Each API invocation is made in a {\it stateless} manner in that each invocation is not dependent on the prior invocation.

\subsubsection{Security}

See \ref{security} for details on how to authenticate API requests as well as how API requests are authorized.

\subsection{JSON-RPC API}

Most API is vended as \href{http://www.jsonrpc.org}{JSON-RPC} encoded HTTP POST invocations.  The data transfer objects (DTOs) that describe the request and the response data as well as the APIs' interfaces exist in the ``haikudepotserver-api'' module in the java package;

\framebox{\tt org.haikuos.haikudepotserver.api1}

The documentation and list of available methods can be obtained by viewing the java interfaces and model objects in that module.

\subsubsection{Example: Get a Package}

In this example, the client knows the {\it name} of the package and would like to get the details of the package.  The java model objects that document the data required in request and the data that can be expected in the response can be found in the project.  The request model is;

\framebox{\tt org.haikuos.haikudepotserver.api1.model.pkg.GetPkgRequest}

The response model is;

\framebox{\tt org.haikuos.haikudepotserver.api1.model.pkg.GetPkgResult}

The actual server method that is invoked as a result of this request can be found at;

\framebox{\tt org.haikuos.haikudepotserver.api1.PkgApi\#getPkg(..)}

You will notice at the top of this interface, there is an annotation that describes the path or ``endpoint'' for this API.  In this case it is ``{\tt /api/v1/pkg}''.  Given a host and port, this can be extrapolated into a URL that can be used to invoke to this method.  An example would be;

\framebox{\tt http://localhost:8080/api/v1/pkg}

The invocation is made using the HTTP protocol to such a URL with the method POST.  The Content-Type HTTP header must be set to "{\tt application/json}" for both the request and the response.  The request object would look something like this;

\begin{verbatim}
{
 "jsonrpc":"2.0",
 "id":4143431,
 "method":"getPkg",
 "params":[{
   "name":"apr",
   "architectureCode":"x86",
   "versionType":"NONE"
 }]
}
\end{verbatim}

The ``id'' value here can be anything.  It must be supplied and is used to correlate a request with a response; the same ``id'' value that arrives in the request is relayed back in the response.  If a client were using the API in an asynchronous manner then being able to correlate the request and the response is very important.

All going well, the following (abridged) form of response would be sent back to the client;

\begin{verbatim}
{
 "jsonrpc":"2.0",
 "id":4143431,
 "result":{
  "name":"apr",
  "hasIcon":true,
  "canEdit":false,
  "versions":[],
  "modifyTimestamp":12345678
 }
}
\end{verbatim}

See the \href{http://www.jsonrpc.org}{JSON-RPC} web site for examples of the response envelope format for the scenario in which an error has arisen in the invocation.

\subsubsection{Error Codes}

A set of known JSON-RPC error codes are agreed between the client and server.  See the JSON-RPC specification for known error codes used for transport-related issues such as invalid parameters.  Application-specific error codes are documented in the java source at;

\framebox{\tt org.haikuos.haikudepotserver.api1.support.Constants}

Some errors such as the validation error (code {\tt -32800}) may also carry additional data that provides detail as to the nature of the error that has arisen.  Java logic for assembling the error payloads can be found at;

\framebox{\tt org.haikuos.haikudepotserver.api1.support.ErrorResolverImpl}

\subsection{REST API}

REST API is generally required where data is inappropriate to encode as JSON-RPC.  This tends to be situations where the data is binary in nature.  An example of this is where a package icon needs to be uploaded.

\subsubsection{Entry Point}

This API will provide the web application's HTML user interface.

\begin{itemize}
\item HTTP Method : GET
\item Path : /
\item Response Content-Type : text/html
\end{itemize}

\subsubsection{Import Repository Data}
\label{api-importrepositorydata}

This API provides a mechanism by which an external client is able to trigger the application to start importing package-related data from a remote repository.  This API is provided as REST because the client is likely to be scripted using a scripting language and REST is the most appropriate protocol to employ in this situation.  This invocation will trigger the import process, but the import process will execute in a background thread in the application server and will not block the client.

\begin{itemize}
\item HTTP Method : GET
\item Path : /importrepositorydata
\item Response Content-Type : text/plain
\item Query Parameters
  \begin{itemize}
  \item {\bf code} : Identifies the repository from which data should be obtained
  \end{itemize}
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The import job was accepted
  \item {\bf 400} : The code was not supplied in the request
  \end{itemize}
\end{itemize}

An example URL is;

\framebox{\tt http://localhost:8080/importrepositorydata?code=haikuportsprod}

\subsubsection{Get Package Icon}

This API is able to provide the icon for a package.  If there is no icon stored then this method will provide a fall-back image if the {\t f} query parameter is configured to ``true'' --- otherwise it will return a 404 HTTP status code.  Providing a fallback image may not be possible in all cases.  The request will return a {\tt Last-Modified} header.  The timestamps of this header will correlate to the {\it modifyTimestamp} that is provided in API responses such as {\tt GetPkResult} and {\tt SearchPkgsResult}.  The value for {\it modifyTimestamp} will be at millisecond resolution, but the HTTP headers will be at second resolution.  The path includes a {\it mediatype-extension} which can have one of the following values;

\begin{itemize}
\item png
\item hvif
\end{itemize}

Details of the API;

\begin{itemize}
\item HTTP Method : GET, HEAD
\item Path : /pkgicon/$<$pkgname$>$.$<$mediatype-extension$>$
\item Response Content-Type : ``image/png'' or ``application/x-vnd.haiku-icon''
\item Query Parameters
  \begin{itemize}
  \item {\bf s} : Either 16 or 32 for the number of pixels; omitt for hivf files
  \item {\bf f} : ``true'' will yield a fallback image in the response if possible
  \end{itemize}
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The icon is provided in the response (for GET)
  \item {\bf 415} : The path did not include ".png" or the size is invalid
  \item {\bf 400} : The package name was not supplied
  \item {\bf 404} : The package was not found or no image was present
  \end{itemize}
\end{itemize}

An example URL for obtaining a bitmap image;

\framebox{\tt http://localhost:8080/pkgicon/apr.png?size=32\&f=true}

An example URL for obtaining a Haiku vector image file image;

\framebox{\tt http://localhost:8080/pkgicon/apr.hvif}


\subsubsection{Get Screenshot Image}

This API is able to produce an image for a screenshot.  The screenshot is identified in the path by its code.  The response will return a {\tt Last-Modified} header.  The timestamps of this header will correlate to the {\it modifyTimestamp} that is provided in API responses such as {\tt GetPkResult} and {\tt SearchPkgsResult}.  The value for {\it modifyTimestamp} will be at millisecond resolution, but the HTTP headers will be at second resolution.  Requests for screenshot image should be accompanied by a target width and height.  These values must be within a range of 1..1500.  The image will maintain its aspect ratio as it is scaled to fit within the supplied target width and height.

\begin{itemize}
\item HTTP Method : GET, HEAD
\item Path : /pkgscreenshot/$<$screenshotcode$>$.png
\item Response Content-Type : image/png
\item Query Parameters
  \begin{itemize}
  \item {\bf tw} : An integer value that describes the width that the image should be scaled to
  \item {\bf th} : An integer value that describes the height that the image should be scaled to
  \end{itemize}
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The image data is provided in the response (for GET)
  \item {\bf 415} : The path did not include ".png" or the target width or height is invalid or the length of the data is too large
  \item {\bf 400} : The screenshot code was not supplied
  \item {\bf 404} : The screenshot was not found
  \end{itemize}
\end{itemize}

An example URL is;

\framebox{\tt http://localhost:8080/pkgscreenshot/a78hw20fh2p20fh122jd92.png?tw=640\&th=480}

\subsubsection{Get Raw Screenshot Image}

This API is able to provide the {\it raw} screenshot data.

\begin{itemize}
\item HTTP Method : GET
\item Path : /pkgscreenshot/$<$screenshotcode$>$/raw
\item Response Content-Type : {\it As per the stored data}
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The image data is provided in the response (for GET)
  \item {\bf 404} : The screenshot was not found for the code supplied
  \end{itemize}
\end{itemize}

An example URL is;

\framebox{\tt http://localhost:8080/pkgscreenshot/a78hw20fh2p20fh122jd92/raw}

\subsubsection{Add Screenshot Image}

This API is able to add an image as a screenshot for the nominated package.  The screenshot will be ordered last.  The payload of the POST must be a PNG image that is a maximum of 1500x1500 pixels and a maximum of 2MB in size.

\begin{itemize}
\item HTTP Method : POST
\item Path : /pkgscreenshot/$<$pkgname$>$/add
\item Query Parameters
  \begin{itemize}
  \item {\bf format} : The string 'png' to define the image format.
  \end{itemize}
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The screenshot image was stored
  \item {\bf 415} : The path did not include ".png" or the size (pixels or data) of the image is invalid or the payload is not PNG image data.
  \item {\bf 404} : The package identified in the path was not able to be found
  \item {\bf 400} : The package name was not supplied
  \end{itemize}
\item Specific Response Headers
  \begin{itemize}
  \item {\bf X-HaikuDepotServer-ScreenshotCode} : Supplies the code of the newly created screenshot.
  \end{itemize}
\end{itemize}

An example URL is;

\framebox{\tt http://localhost:8080/pkgscreenshot/apr/add?format=png}

\subsubsection{Medium-Term Maintenance}

Medium-term maintenance includes tasks that should be undertaken every hour or so that clean-up disused resources.  An example is removing expired password-reset tokens from the database.  Medium-term maintenance is triggered externally (from a process such as {\it cron}) rather than on an internal scheduler in order to simplify a multi-instance deployment.

\begin{itemize}
\item HTTP Method : GET
\item Path : /maintenance/mediumterm
\item Expected HTTP Status Codes
  \begin{itemize}
  \item {\bf 200} : The maintenance request was accepted
  \item {\bf *} : The maintenance job was not accepted
  \end{itemize}
\end{itemize}




